﻿using System;
using System.Windows;
using PSE.Deployment.ConfigurationManager.Controls;
using PSE.Deployment.Engine.Enums;
using PSE.Deployment.SetupBase.Parameter.Enums;

namespace PSE.Deployment.SetupBase.UI
{
    public partial class InstallationProgress : BaseWindow
    {
        public event Action ExecutionPause;
        public event Action ExecutionStop;
        public event Action ExecutionContinue;

        public InstallationProgress()
        {
            this.InitializeComponent();
            this.DataContext = this;
            this.ConfirmOnClosing = true;

            this.Closed += new EventHandler(InstallationProgress_Closed);

            if (SetupMainFactory.GetInstance().Parameter.SetupMode == SetupMode.HotFix ||
                SetupMainFactory.GetInstance().Parameter.SetupMode == SetupMode.ServicePack)
            {
                BtnCancel.Visibility = Visibility.Hidden;
            }
        }

        void InstallationProgress_Closed(object sender, EventArgs e)
        {
            this.Dispatcher.InvokeShutdown();
        }

        public string GroupDescription
        {
            get { return (string)GetValue(GroupDescriptionProperty); }
            protected set { SetValue(GroupDescriptionProperty, value); }
        }

        public static readonly DependencyProperty GroupDescriptionProperty =
            DependencyProperty.Register("GroupDescription", typeof(string), typeof(InstallationProgress), new UIPropertyMetadata(String.Empty));

        public string StepDescription
        {
            get { return (string)GetValue(StepDescriptionProperty); }
            protected set { SetValue(StepDescriptionProperty, value); }
        }

        public static readonly DependencyProperty StepDescriptionProperty =
            DependencyProperty.Register("StepDescription", typeof(string), typeof(InstallationProgress), new UIPropertyMetadata(String.Empty));

        public string ProgressDescription
        {
            get { return (string)GetValue(ProgressDescriptionProperty); }
            protected set { SetValue(ProgressDescriptionProperty, value); }
        }

        public static readonly DependencyProperty ProgressDescriptionProperty =
            DependencyProperty.Register("ProgressDescription", typeof(string), typeof(InstallationProgress), new UIPropertyMetadata(String.Empty));

        public void UpdateConfirmOnClosingMessage(string message)
        {
            if (System.Threading.Thread.CurrentThread == this.Dispatcher.Thread)
            {
                this.ConfirmOnClosingMessage = message;
            }
            else
            {
                this.Dispatcher.Invoke(new Action<string>(UpdateConfirmOnClosingMessage), message);
            }
        }

        public void UpdateStepDescription(string description)
        {
            if (System.Threading.Thread.CurrentThread == this.Dispatcher.Thread)
            {
                StepDescription = description;
            }
            else
            {
                this.Dispatcher.Invoke(new Action<string>(UpdateStepDescription), description);
            }
        }

        public void UpdateGroupDescription(string description)
        {
            if (System.Threading.Thread.CurrentThread == this.Dispatcher.Thread)
            {
                GroupDescription = description;
            }
            else
            {
                this.Dispatcher.Invoke(new Action<string>(UpdateGroupDescription), description);
            }
        }

        public void RunDispatcher()
        {
            if (System.Threading.Thread.CurrentThread == this.Dispatcher.Thread)
            {
                if (!System.Windows.Threading.Dispatcher.CurrentDispatcher.HasShutdownStarted)
                    System.Windows.Threading.Dispatcher.Run();
            }
            else
            {
                this.Dispatcher.Invoke(new Action(RunDispatcher));
            }
        }

        public void IncrementTotalProgress()
        {
            if (System.Threading.Thread.CurrentThread == this.Dispatcher.Thread)
            {
                this.IncrementTotalProgress((int)prgTotalProgress.Value + 1);
            }
            else
            {
                this.Dispatcher.Invoke(new Action(IncrementTotalProgress));
            }
        }

        public void DecrementTotalProgress()
        {
            if (System.Threading.Thread.CurrentThread == this.Dispatcher.Thread)
            {
                this.IncrementTotalProgress((int)prgTotalProgress.Value - 1);
            }
            else
            {
                this.Dispatcher.Invoke(new Action(DecrementTotalProgress));
            }
        }

        public void IncrementTotalProgress(int currentProgress)
        {
            if (System.Threading.Thread.CurrentThread == this.Dispatcher.Thread)
            {
                if (currentProgress < 0)
                {
                    prgTotalProgress.Value = 0;
                }
                if (currentProgress <= prgTotalProgress.Maximum)
                {
                    prgTotalProgress.Value = currentProgress;
                }
                else
                {
                    prgTotalProgress.Value = prgTotalProgress.Maximum;
                }

                lblTotalProgress.Content = Convert.ToInt32((prgTotalProgress.Value * 100) / prgTotalProgress.Maximum).ToString() + "%";
                //lblTotalProgress.Content = prgTotalProgress.Value.ToString() + " / " + prgTotalProgress.Maximum.ToString();
            }
            else
            {
                this.Dispatcher.Invoke(new Action<int>(IncrementTotalProgress), currentProgress);
            }
        }

        public void ResetTotalProgress(int maximumProgress)
        {
            if (System.Threading.Thread.CurrentThread == this.Dispatcher.Thread)
            {
                prgTotalProgress.Maximum = maximumProgress <= 0 ? 100 : maximumProgress;

                lblTotalProgress.Content = Convert.ToInt32((prgTotalProgress.Value * 100) / prgTotalProgress.Maximum).ToString() + "%";
                //lblTotalProgress.Content = prgTotalProgress.Value.ToString() + " / " + prgTotalProgress.Maximum.ToString();
            }
            else
            {
                this.Dispatcher.Invoke(new Action<int>(ResetTotalProgress), maximumProgress);
            }
        }

        public void IncrementStepProgress(int currentProgress, string progressDescription)
        {
            if (System.Threading.Thread.CurrentThread == this.Dispatcher.Thread)
            {
                this.ProgressDescription = progressDescription;

                if (currentProgress < 0)
                {
                    prgTotalProgress.Value = 0;
                }
                if (currentProgress <= prgStepProgress.Maximum)
                {
                    prgStepProgress.Value = currentProgress;
                }
                else
                {
                    prgStepProgress.Value = prgStepProgress.Maximum;
                }

                lblStepProgress.Content = Convert.ToInt32((prgStepProgress.Value * 100) / prgStepProgress.Maximum).ToString() + "%";
                //lblStepProgress.Content = prgStepProgress.Value.ToString() + " / " + prgStepProgress.Maximum.ToString();
            }
            else
            {
                this.Dispatcher.Invoke(new Action<int, string>(IncrementStepProgress), currentProgress, progressDescription);
            }
        }

        public void ResetStepProgress(int maximumProgress)
        {
            if (System.Threading.Thread.CurrentThread == this.Dispatcher.Thread)
            {
                prgStepProgress.Value = 0;
                prgStepProgress.Maximum = maximumProgress <= 0 ? 100 : maximumProgress;

                lblStepProgress.Content = Convert.ToInt32((prgStepProgress.Value * 100) / prgStepProgress.Maximum).ToString() + "%";
                //lblStepProgress.Content = prgStepProgress.Value.ToString() + " / " + prgStepProgress.Maximum.ToString();
            }
            else
            {
                this.Dispatcher.Invoke(new Action<int>(ResetStepProgress), maximumProgress);
            }
        }

        public StepErrorAction ShowExecutionError(Exception ex, bool showIgnoreButton)
        {
            if (System.Threading.Thread.CurrentThread == this.Dispatcher.Thread)
            {
                ErrorNotification errorNotification = new ErrorNotification(showIgnoreButton);
                errorNotification.Owner = this;
                errorNotification.ErrorMessage = ex.Message;
                errorNotification.ShowDialog();

                if (errorNotification.ErrorAction == StepErrorAction.CancelParent)
                {
                    this.AllowClose = false;
                    this.AllowCancel = false;
                    this.NavigationAction = StepNavigationAction.Cancel;
                }

                return errorNotification.ErrorAction;
            }
            else
            {
                return (StepErrorAction)this.Dispatcher.Invoke(new Func<Exception, bool, StepErrorAction>(ShowExecutionError), ex, showIgnoreButton);
            }
        }

        private void Cancel()
        {
            ExecutionPause();

            if (ConfigurationMessageBox.Show(string.Format("Deseja realmente cancelar {0}?", GroupDescription) + this.ConfirmOnClosingMessage, "Atenção", ConfigurationMessageBoxButton.YesNo, ConfigurationMessageBoxImage.Question) == ConfigurationMessageBoxResult.Yes)
            {
                this.NavigationAction = StepNavigationAction.Cancel;
                this.AllowClose = false;
                this.AllowCancel = false;
                ExecutionStop();
            }
            else
            {
                ExecutionContinue();
            }
        }

        protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
        {
            if (this.ConfirmOnClosing)
            {
                if (!NavigationAction.HasValue)
                {
                    Cancel();
                }

                e.Cancel = true;
            }
        }

        protected override void OnCancelClick(RoutedEventArgs e)
        {
            Cancel();
        }
    }
}